package com.xxx.userservice.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.xxx.userservice.pojo.entity.User;
import com.xxx.userservice.service.UserService;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;

@Slf4j
@RestController
@RequestMapping(value = "/user")
@RefreshScope   // 开启nacos配置自动刷新
public class UserController {

    @Value("${userInfo.name}")
    private String name;
    @Value("${userInfo.age}")
    private String age;
    @Value("${userInfo.sex}")
    private String sex;

    @Resource
    private UserService userService;

    /**
     * http://localhost:9081/user/index
     */
    @GetMapping(value = "/index")
    public String index (){
        return "this is user-service";
    }

    /**
     * 测试Nacos配置中心
     * http://localhost:9081/user/testNacosConfig
     */
    @GetMapping(value = "/testNacosConfig")
    public String testNacosConfig (){
        return "name: " + name + ", age: " + age + ", sex: " + sex;
    }

    /**
     * 测试Nacos服务发现
     * http://localhost:9081/user/testNacosDiscovery/11111111111111
     */
    @RequestMapping(value = "/testNacosDiscovery/{string}", method = RequestMethod.GET)
    public String testNacosDiscovery(@PathVariable String string) {
        return "Hello Nacos Discovery " + string;
    }

    /**
     * 测试db
     * http://localhost:9081/user/testMySQL?userId=1
     */
    @GetMapping(value = "/testMySQL")
    @ResponseBody
    public User testDb (int userId){
        return userService.getByUserId(userId);
    }

    /**
     * 添加用户
     * http://localhost:9081/user/addUser
     */
    @PostMapping(value = "/addUser")
    @ResponseBody
    public boolean addUser (@RequestBody com.xxx.util.pojo.User user){
        User entity = new User();
        BeanUtils.copyProperties(user, entity);
        return userService.save(entity);
    }

    /**
     * 测试seata AT模式
     * http://localhost:9081/user/deductMoneyByAT?userId=1&amount=10
     */
    @GetMapping(value = "/deductMoneyByAT")
    @ResponseBody
    public boolean deductMoneyByAT (String userId, BigDecimal amount){
        User entity = userService.getByUserId(Integer.parseInt(userId));
        BigDecimal oldMoney = entity.getMoney();
        BigDecimal newMoney = oldMoney.subtract(amount);
        entity.setMoney(newMoney);
        return userService.updateById(entity);
    }

    /**
     * 测试seata TCC模式
     * http://localhost:9081/user/deductMoneyByTCC?userId=1&amount=20
     */
    @GetMapping(value = "/deductMoneyByTCC")
    @ResponseBody
    public boolean deductMoneyByTCC (String userId, BigDecimal amount){
        // 判断用户可用余额是否足够
        BigDecimal money = userService.getMoney(userId);
        if(money == null || money.compareTo(amount) < 0) {
            log.info("deductMoneyByTCC====================余额不足. userId:{}", userId);
            return false;
        }
        return userService.prepareDeduct(userId, amount);
    }

    /**
     * http://localhost:9081/user/timeout
     */
    @GetMapping(value = "/timeout")
    public String timeout (){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return "timeout";
    }

    /**
     * http://localhost:9081/user/exception
     */
    @GetMapping(value = "/exception")
    public String exception (){
        int n = 10 /0;
        return "exception";
    }

    /**
     * 热点限流
     * http://localhost:9999/user/testHotKey?p1=1&p2=2
     */
    @GetMapping(value = "/testHotKey")
//    @SentinelResource(value = "testHotKey")   // 热点限流注解
    @SentinelResource(value = "testHotKey", blockHandler = "testHotKeyBlockHandler")   // 热点限流注解
    public String testHotKey (@RequestParam(value = "p1",required = false) String p1, @RequestParam(value = "p2",required = false) String p2){
        return "testHotKey";
    }

    // 被热点限流后的降级处理
    public String testHotKeyBlockHandler (String p1, String p2, BlockException e){
        return "testHotKey,热点流控降级";
    }

}
